using System.Collections.Generic;
using UnityEngine;
using static WaterCylinder;


public enum BulletTag{
    None = 0,
    /// <summary>
    /// 近战子弹对象，用于碰撞检测
    /// </summary>
    Melee,
    /// <summary>
    /// 穿透敌方
    /// </summary>
    PassEnemy,
    /// <summary>
    /// 穿透方块
    /// </summary>
    PassBlock,
    /// <summary>
    /// 穿透墙壁
    /// </summary>
    PassWall,
    /// <summary>
    /// 穿透玩家
    /// </summary>
    PassPlayer,
    /// <summary>
    /// 单次伤害，伤害在Enter方法里计算
    /// </summary>
    OnceDamage,
    /// <summary>
    /// 持续伤害，伤害Stay里计算
    /// </summary>
    DoTDamage,
    
}

public class Bullet : Entity
{   
    #region 静态方法
    /// <summary>
    /// 不使用预制体创建子弹
    /// </summary>
    /// <param name="name">子弹名称</param>
    /// <param name="tags">子弹标签</param>
    /// <param name="damage">子弹伤害</param>
    /// <param name="source">子弹来源</param>
    /// <param name="target">子弹目标</param>
    /// <param name="toward">子弹朝向</param>
    /// <param name="speed">子弹速度</param>
    /// <param name="OnHurt">子弹伤害时事件</param>
    /// <param name="OnWay">子弹运动时事件</param>
    /// <returns></returns>
    public static Bullet CreatBullet(string name, BulletTag[] tags, Damage damage, Entity source, Entity target,
        Vector2 toward, float speed, float lifetime,
        Function OnShot, Function OnHurt, Function OnWay, Function OnDisappear,
        Vector2 pos){
        GameObject obj = Creat(GetPrefab("DefaultObject/Bullet"), pos);
        Bullet b = obj.GetComponent<Bullet>();
        b.name = name;
        b.bulletTags.AddRange(tags);
        b.damage = damage;
        b.source = source;
        b.target = target;
        b.toward = toward;
        b.speed = speed;
        b.lifetime = lifetime;
        b.OnShot = OnShot;
        b.OnHurt = OnHurt;
        b.OnWay = OnWay;
        b.OnDisappear = OnDisappear;
        b.OnCreate();
        return b;
    }
    
    /// <summary>
    /// 使用预制体创建子弹
    /// </summary>
    /// <param name="prefab"></param>
    /// <param name="source">子弹来源</param>
    /// <param name="target">子弹目标</param>
    /// <returns></returns>
    public static Bullet CreatBullet(GameObject prefab, Entity source, Entity target, Vector2 pos){
        GameObject obj = Creat(prefab, pos);
        Bullet b = obj.GetComponent<Bullet>();
        b.source = source;
        b.target = target;
        b.OnCreate();
        return b;
    }
    
    /// <summary>
    /// 使用预制体创建子弹，传入方向和速度
    /// </summary>
    /// <param name="prefab"></param>
    /// <param name="source"></param>
    /// <param name="toward"></param>
    /// <param name="speed"></param>
    /// <returns></returns>
    public static Bullet CreatBullet(GameObject prefab, Entity source, Vector2 toward, float speed){
        GameObject obj = Creat(prefab, source.weaponPos);
        Bullet b = obj.GetComponent<Bullet>();
        b.toward = toward;
        b.source = source;
        b.speed = speed;
        b.OnCreate();
        return b;
    }

    /// <summary>
    /// 创建默认子弹
    /// </summary>
    /// <param name="source"></param>
    /// <param name="toward"></param>
    /// <returns></returns>
    public static Bullet CreatBullet(Entity source, Vector2 toward){
        return CreatBullet(GetPrefab("DefaultObject/Bullet"), source, toward, 8);
    }
    
    /// <summary>
    /// 创建近战子弹
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="radius"></param>
    /// <returns></returns>
    public static Bullet CreatMeleeBullet(Entity entity, float radius = 1){
        Bullet b = CreatBullet(GetPrefab("Bullets/MeleeBullet"), entity, null, entity.transform.position);
        b.transform.parent = entity.transform;
        b.transform.localPosition = Vector2.zero;
        b.GetComponent<CircleCollider2D>().radius = radius;
        return b;
    }

    #endregion
    
    #region 属性
    [SerializeField]
    private List<BulletTag> bulletTags = new List<BulletTag>();
    public bool BulletTagCheck(BulletTag t){
        return bulletTags.Contains(t);
    }
    
    [SerializeField]
    private List<EntityTag> ignoreTags = new List<EntityTag>();
    public bool isIgnoreOtherBullet = true;
    public bool IgnoreTagCheck(EntityTag t){
        return ignoreTags.Contains(t);
    }
    public bool IgnoreTagCheck(List<EntityTag> list){
        return list.Exists(x => ignoreTags.Contains(x));
    }

    /// <summary>
    /// 子弹伤害
    /// </summary>
    public Damage damage;
    /// <summary>
    /// 存在时间，为-1则为永久存在
    /// </summary>
    public float lifetime;
    /// <summary>
    /// 当前存在时间
    /// </summary>
    [SerializeField]
    [Tooltip("Disable")]
    private float time = 0;
    /// <summary>
    /// 子弹来源实体
    /// </summary>
    [Tooltip("Disable")]
    public Entity source;
    /// <summary>
    /// 子弹目标
    /// </summary>
    [Tooltip("Disable")]
    public Entity target;
    
    #endregion
    #region 代理

    /// <summary>
    /// 子弹事件代理
    /// </summary>
    /// <param name="other"></param>
    public delegate void Function(Entity other);
    /// <summary>
    /// 创建子弹时的事件代理
    /// </summary>
    public Function OnShot;
    /// <summary>
    /// 子弹到达目标事件伤害事件前代理
    /// </summary>
    public Function OnHurt;
    /// <summary>
    /// 子弹行动时代理
    /// </summary>
    public Function OnWay;
    /// <summary>
    /// 子弹消失时的处理
    /// </summary>
    public Function OnDisappear;

    #endregion

    #region 实体方法

    /// <summary>
    /// 创建时
    /// </summary>
    public virtual void OnCreate(){
        //无视子弹与来源碰撞
        Collider2D c1 = GetComponent<Collider2D>();
        Collider2D c2 = source.GetComponent<Collider2D>();
        if(c2 != null && c1 != null){
            Physics2D.IgnoreCollision(c1, c2, true);
        }
        OnShot?.Invoke(target);
    }
    
    protected override void OnEntityTriggerEnter(Entity other){
        if(!IgnoreTagCheck(other.tags) && !(isIgnoreOtherBullet && other.type == EntityType.Bullet)){
            OnHurt?.Invoke(other);
            other.ToDamage(damage, source);
        }
        //没有穿透则消失
        if((!BulletTagCheck(BulletTag.PassEnemy) && other.type == EntityType.Enemy)
            || (!BulletTagCheck(BulletTag.PassBlock) && other.type == EntityType.Block)
            || (!BulletTagCheck(BulletTag.PassPlayer) && other.type == EntityType.Player)){
            Die(other);
        }
    }

    protected override void OnEntityTrigger(Entity other){
        if(!IgnoreTagCheck(other.tags) && !(isIgnoreOtherBullet && other.type == EntityType.Bullet)){
            if(BulletTagCheck(BulletTag.DoTDamage)){
                OnHurt?.Invoke(other);
                other.ToDamage(damage, source);
            }
        }
    }

    protected override void OnOtherTriggerEnter(Collider2D other){
        // 无视墙
        if(!BulletTagCheck(BulletTag.PassWall) && other.gameObject.tag == "Wall"){
            Die(null);
        }
    }

    protected override void OnProcess(){
        time += processTime;
        if(lifetime > 0 && time > lifetime){
            Die(null);
        }
        OnWay?.Invoke(target);
    }

    protected override void OnUpdate(){
        Move(toward, speed);
    }

    protected override void OnDead(Entity other){
        OnDisappear?.Invoke(other);
    }

    #endregion

    public void SetDamage(Entity entity = null){
        if(entity == null){
            entity = source;
        }
        damage.value = entity.GetDamage(damage);
    }

}
